﻿using System;
using System.ComponentModel;
using System.Globalization;
using System.Text.RegularExpressions;

namespace Microsoft.Office.OneNote
{
    public sealed class OneNoteColorConverter : TypeConverter
    {
        public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
        {
            if (sourceType == typeof(String))
            {
                return true;
            }

            return base.CanConvertFrom(context, sourceType);
        }

        public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
        {
            if (destinationType == typeof(String))
            {
                return true;
            }

            return base.CanConvertTo(context, destinationType);
        }

        public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
        {
            string str = (value as string);

            if (str != null)
            {
                OneNoteColor? result = Convert(str);

                if (result.HasValue)
                {
                    return result.Value;
                }
            }

            return base.ConvertFrom(context, culture, value);
        }

        public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType)
        {
            if (destinationType == typeof(String))
            {
                if (value == null)
                {
                    return string.Empty;
                }

                return value.ToString();
            }

            return base.ConvertTo(context, culture, value, destinationType);
        }

        internal static OneNoteColor? Convert(string str)
        {
            Match match = ParseRegex.Match(str);

            if (match.Success)
            {
                if (match.Groups["RGB"].Success)
                {
                    byte r, g, b;

                    string rgb = match.Groups["RGB"].Value;

                    if (TryParseByte(rgb, 1, out r) &&
                        TryParseByte(rgb, 3, out g) &&
                        TryParseByte(rgb, 5, out b))
                    {
                        return OneNoteColor.FromRgb(r, g, b);
                    }
                }

                else if (match.Groups["None"].Success)
                {
                    return OneNoteColor.None;
                }

                else if (match.Groups["Auto"].Success)
                {
                    return OneNoteColor.Automatic;
                }
            }

            return null;
        }

        private static bool TryParseByte(string str, int offset, out byte result)
        {
            if (offset + 2 > str.Length)
            {
                result = 0;
                return false;
            }

            string substr = str.Substring(offset, 2);

            return byte.TryParse(substr, NumberStyles.HexNumber, CultureInfo.InvariantCulture, out result);
        }

        private static readonly Regex ParseRegex = new Regex(@"
            ^
            (?<RGB> \#[a-fA-F0-9]{6} ) |
            (?<None> none            ) |
            (?<Auto> automatic       ) $",

            RegexOptions.Compiled |
            RegexOptions.CultureInvariant |
            RegexOptions.IgnorePatternWhitespace);
    }
}
